<template>
  <div class="big-file-upload">
    <div class="upload-area"
         @drop="handleDrop"
         @dragover="handleDragOver"
         @dragleave="handleDragLeave"
         :class="{ 'drag-over': isDragOver }"
         @click="triggerFileInput">
      <div class="upload-content">
        <i class="upload-icon">📁</i>
        <h3>拖拽文件到此处或点击上传</h3>
        <p>支持大文件上传，最大 {{ maxFileSizeMB }}MB</p>
        <input
          type="file"
          ref="fileInput"
          @change="handleFileSelect"
          style="display: none"
          :multiple="multiple"
        />
      </div>
    </div>

    <!-- 上传文件列表 -->
    <div class="file-list" v-if="fileList.length > 0">
      <div v-for="file in fileList" :key="file.id" class="file-item">
        <div class="file-info">
          <div class="file-name">{{ file.name }}</div>
          <div class="file-size">{{ formatFileSize(file.size) }}</div>
        </div>

        <div class="upload-progress">
          <!-- 分片上传进度 -->
          <div class="chunk-progress" v-if="file.chunked">
            <div class="progress-bar">
              <div class="progress-fill" :style="{ width: file.progress + '%' }"></div>
            </div>
            <div class="progress-text">
              {{ file.uploadedChunks }}/{{ file.totalChunks }} 分片
              ({{ file.progress.toFixed(1) }}%)
            </div>
          </div>

          <!-- 普通上传进度 -->
          <div class="normal-progress" v-else>
            <div class="progress-bar">
              <div class="progress-fill" :style="{ width: file.progress + '%' }"></div>
            </div>
            <div class="progress-text">{{ file.progress.toFixed(1) }}%</div>
          </div>
        </div>

        <div class="file-actions">
          <button v-if="file.status === 'waiting'" @click="startUpload(file)" class="btn-start">
            开始上传
          </button>
          <button v-if="file.status === 'uploading'" @click="pauseUpload(file)" class="btn-pause">
            暂停
          </button>
          <button v-if="file.status === 'paused'" @click="resumeUpload(file)" class="btn-resume">
            继续
          </button>
          <button @click="cancelUpload(file)" class="btn-cancel">取消</button>

          <span v-if="file.status === 'completed'" class="status-completed">✅ 完成</span>
          <span v-if="file.status === 'error'" class="status-error">❌ 失败</span>
        </div>

        <!-- 错误信息 -->
        <div v-if="file.error" class="error-message">
          {{ file.error }}
        </div>
      </div>
    </div>

    <!-- 上传统计 -->
    <div class="upload-stats" v-if="fileList.length > 0">
      <div class="stats-item">
        <span>总文件数:</span>
        <strong>{{ fileList.length }}</strong>
      </div>
      <div class="stats-item">
        <span>上传中:</span>
        <strong>{{ uploadingCount }}</strong>
      </div>
      <div class="stats-item">
        <span>已完成:</span>
        <strong>{{ completedCount }}</strong>
      </div>
      <div class="stats-item">
        <span>总大小:</span>
        <strong>{{ formatFileSize(totalSize) }}</strong>
      </div>
    </div>

    <!-- 完成操作按钮 -->
    <div class="upload-actions" v-if="fileList.length > 0 && completedCount === fileList.length && uploadingCount === 0">
      <button class="btn-complete" @click="handleComplete">
        ✅ 完成并关闭
      </button>
    </div>
  </div>
</template>

<script>
import { fileService } from '@/services/fileService';
import { chunkManager } from '@/router/chunkManager';
import { childEnglishApi } from '@/api/childEnglishApi';

export default {
  name: 'BigFileUpload',
  props: {
    // 最大文件大小（MB）
    maxFileSize: {
      type: Number,
      default: 1024 // 1GB
    },
    // 分片大小（MB）
    chunkSize: {
      type: Number,
      default: 5
    },
    // 是否支持多文件上传
    multiple: {
      type: Boolean,
      default: true
    },
    // 并发上传数量
    concurrentUploads: {
      type: Number,
      default: 3
    },
    // 文件类型：courseware（课件）或 picturebook（绘本）
    fileType: {
      type: String,
      default: null
    }
  },
  data() {
    return {
      fileList: [],
      isDragOver: false,
      uploadQueue: [],
      activeUploads: 0
    };
  },
  computed: {
    maxFileSizeMB() {
      return this.maxFileSize;
    },
    maxFileSizeBytes() {
      return this.maxFileSize * 1024 * 1024;
    },
    chunkSizeBytes() {
      return this.chunkSize * 1024 * 1024;
    },
    uploadingCount() {
      return this.fileList.filter(f => f.status === 'uploading').length;
    },
    completedCount() {
      return this.fileList.filter(f => f.status === 'completed').length;
    },
    totalSize() {
      return this.fileList.reduce((sum, file) => sum + file.size, 0);
    }
  },
  methods: {
    // 触发文件选择
    triggerFileInput() {
      this.$refs.fileInput.click();
    },

    // 处理文件选择
    handleFileSelect(event) {
      const files = Array.from(event.target.files);
      this.addFiles(files);
      event.target.value = ''; // 重置input
    },

    // 处理拖拽放置
    handleDrop(event) {
      event.preventDefault();
      this.isDragOver = false;

      const files = Array.from(event.dataTransfer.files);
      this.addFiles(files);
    },

    // 处理拖拽悬停
    handleDragOver(event) {
      event.preventDefault();
      this.isDragOver = true;
    },

    // 处理拖拽离开
    handleDragLeave(event) {
      event.preventDefault();
      this.isDragOver = false;
    },

    // 添加文件到上传列表
    addFiles(files) {
      files.forEach(file => {
        // 验证文件大小
        if (file.size > this.maxFileSizeBytes) {
          this.$message.error(`文件 "${file.name}" 超过最大限制 ${this.maxFileSizeMB}MB`);
          return;
        }

        // 检查是否已存在
        if (this.fileList.find(f => f.name === file.name && f.size === file.size)) {
          this.$message.warning(`文件 "${file.name}" 已存在上传列表中`);
          return;
        }

        const fileItem = {
          id: this.generateFileId(),
          file: file,
          name: file.name,
          size: file.size,
          progress: 0,
          status: 'waiting',
          error: null,
          // 分片相关属性
          chunked: file.size > this.chunkSizeBytes,
          totalChunks: file.size > this.chunkSizeBytes ?
            Math.ceil(file.size / this.chunkSizeBytes) : 1,
          uploadedChunks: 0,
          chunkStatus: {},
          md5: null
        };

        this.fileList.push(fileItem);
      });
    },

    // 开始上传文件
    async startUpload(fileItem) {
      try {
        fileItem.status = 'uploading';

        if (fileItem.chunked) {
          await this.uploadWithChunks(fileItem);
        } else {
          await this.uploadNormal(fileItem);
        }

      } catch (error) {
        this.handleUploadError(fileItem, error);
      }
    },

    // 分片上传
    async uploadWithChunks(fileItem) {
      try {
        // 计算文件MD5（大文件可以跳过或使用文件头计算）
        fileItem.md5 = await chunkManager.calculateFileMD5(fileItem.file);

        // 检查分片状态 - 直接使用 API
        const response = await childEnglishApi.checkChunkStatus({
          fileMd5: fileItem.md5,
          fileName: fileItem.name,
          fileSize: fileItem.size,
          chunkSize: this.chunkSizeBytes,
          totalChunks: fileItem.totalChunks
        });

        // 处理响应数据 - 支持多种响应格式
        let chunkStatus = null;
        if (response && typeof response === 'object') {
          // 如果响应有 data 字段，使用 data
          if (response.data && typeof response.data === 'object') {
            chunkStatus = response.data;
          } else if (response.status !== undefined || response.duplicate !== undefined) {
            // 如果响应本身包含 status 或 duplicate 字段，直接使用
            chunkStatus = response;
          } else {
            // 其他情况，尝试使用 response
            chunkStatus = response;
          }
        } else {
          chunkStatus = response;
        }
        
        // 确保 chunkStatus 是对象
        if (!chunkStatus || typeof chunkStatus !== 'object') {
          throw new Error('无效的分片状态响应');
        }
        
        if (chunkStatus.status === 'completed') {
          // 检查是否是重复上传
          if (chunkStatus.duplicate === true) {
            // 重复上传，显示错误提示
            const errorMessage = chunkStatus.message || '文件已存在，不能重复上传';
            fileItem.status = 'error';
            fileItem.error = errorMessage;
            fileItem.progress = 0;
            
            console.warn('文件重复上传:', {
              name: fileItem.name,
              existingFile: chunkStatus.originalName || chunkStatus.fileName,
              message: errorMessage
            });
            
            this.$message.error(`文件 "${fileItem.name}" 上传失败: ${errorMessage}`);
            // 不抛出错误，直接返回，避免触发 catch 块
            this.$emit('upload-error', fileItem, new Error(errorMessage));
            return;
          }
          
          // 文件已存在（可能是断点续传），直接完成
          fileItem.progress = 100;
          fileItem.status = 'completed';
          fileItem.finalFileName = chunkStatus.fileName || fileItem.name;
          fileItem.completed = true; // 确保completed标志被设置
          
          console.log('文件已存在，直接完成:', {
            name: fileItem.name,
            finalFileName: fileItem.finalFileName,
            status: fileItem.status
          });
          
          this.$message.success(`文件 "${fileItem.name}" 已存在，无需重复上传`);
          this.$emit('upload-completed', fileItem);
          return;
        }

        // 更新已上传的分片
        if (chunkStatus.uploadedChunks && Array.isArray(chunkStatus.uploadedChunks)) {
          fileItem.uploadedChunks = chunkStatus.uploadedChunks.length;
          fileItem.chunkStatus = chunkStatus;
        } else {
          fileItem.uploadedChunks = 0;
          fileItem.chunkStatus = chunkStatus || {};
        }

        // 上传分片（chunkManager.uploadFile 会自动处理合并）
        // 注意：chunkManager.uploadFile 内部已经包含了合并逻辑，不需要再次调用合并
        
        // 优先使用prop传入的fileType，否则根据文件扩展名判断
        let fileType = this.fileType;
        if (!fileType) {
          const extension = fileItem.name.substring(fileItem.name.lastIndexOf('.') + 1).toLowerCase();
          if (['pdf', 'ppt', 'pptx', 'doc', 'docx', 'txt'].includes(extension)) {
            fileType = 'courseware';
          } else if (['jpg', 'jpeg', 'png', 'gif', 'pdf'].includes(extension)) {
            fileType = 'picturebook';
          } else if (['mp3', 'wav', 'ogg', 'flac', 'aac', 'm4a', 'wma', 'mp4'].includes(extension)) {
            fileType = 'audio';
          }
        }
        
        const uploadResult = await chunkManager.uploadFile(
          fileItem.file,
          fileItem.md5,
          this.chunkSizeBytes,
          {
            onProgress: (chunkNumber, progress) => {
              this.updateChunkProgress(fileItem, chunkNumber, progress);
            },
            onChunkComplete: (chunkNumber) => {
              this.handleChunkComplete(fileItem, chunkNumber);
            },
            fileType: fileType
          }
        );

        // chunkManager.uploadFile 已经完成了合并，直接更新状态
        const mergeResult = uploadResult || {};
        fileItem.progress = 100;
        fileItem.status = 'completed';
        fileItem.finalFileName = mergeResult.fileName || fileItem.name;
        fileItem.completed = true;

        console.log('文件上传完成:', {
          name: fileItem.name,
          finalFileName: fileItem.finalFileName,
          status: fileItem.status,
          progress: fileItem.progress,
          mergeResult: mergeResult
        });

        this.$emit('upload-completed', fileItem);
      } catch (error) {
        console.error('分片上传失败:', error);
        throw error;
      }
    },

    // 普通上传（小文件）
    async uploadNormal(fileItem) {
      try {
        const response = await fileService.uploadFile(fileItem.file, {
          onUploadProgress: (progressEvent) => {
            const progress = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );
            fileItem.progress = progress;
          },
          fileType: this.fileType // 传递文件类型
        });

        const result = response.data || response;
        fileItem.progress = 100;
        fileItem.status = 'completed';
        fileItem.finalFileName = result.fileName || fileItem.name;
        fileItem.completed = true; // 确保completed标志被设置

        console.log('普通上传成功:', {
          name: fileItem.name,
          finalFileName: fileItem.finalFileName,
          status: fileItem.status,
          progress: fileItem.progress
        });

        this.$emit('upload-completed', fileItem);
      } catch (error) {
        console.error('普通上传失败:', error);
        throw error;
      }
    },

    // 暂停上传
    pauseUpload(fileItem) {
      fileItem.status = 'paused';
      chunkManager.pauseUpload(fileItem.md5);
    },

    // 继续上传
    resumeUpload(fileItem) {
      fileItem.status = 'uploading';
      this.startUpload(fileItem);
    },

    // 取消上传
    cancelUpload(fileItem) {
      fileItem.status = 'cancelled';
      if (fileItem.chunked && fileItem.md5) {
        chunkManager.cancelUpload(fileItem.md5);
        fileService.cleanupChunks(fileItem.md5);
      }
      this.removeFile(fileItem);
    },

    // 更新分片进度
    updateChunkProgress(fileItem, chunkNumber, progress) {
      // 计算整体进度
      const chunkProgress = (1 / fileItem.totalChunks) * 100;
      const baseProgress = (fileItem.uploadedChunks / fileItem.totalChunks) * 100;
      fileItem.progress = baseProgress + (chunkProgress * (progress / 100));
    },

    // 处理分片完成
    handleChunkComplete(fileItem, chunkNumber) {
      fileItem.uploadedChunks++;
      fileItem.chunkStatus[chunkNumber] = 'completed';

      // 更新整体进度
      fileItem.progress = (fileItem.uploadedChunks / fileItem.totalChunks) * 100;
    },

    // 处理上传错误
    handleUploadError(fileItem, error) {
      console.error('上传错误:', error);
      fileItem.status = 'error';
      
      // 提取错误消息，处理各种错误类型
      let errorMessage = '上传失败';
      
      try {
        // 确保 error 存在且是对象或字符串
        if (!error) {
          errorMessage = '上传失败，未知错误';
        } else if (error instanceof Error) {
          // Error 对象
          errorMessage = error.message || '上传失败';
        } else if (error.message) {
          // 有 message 属性的对象
          errorMessage = error.message;
        } else if (error.response) {
          // Axios错误响应
          if (error.response.data) {
            const data = error.response.data;
            if (typeof data === 'string') {
              errorMessage = data;
            } else if (data && typeof data === 'object') {
              // 安全地访问嵌套属性
              if (data.message) {
                errorMessage = data.message;
              } else if (data.msg) {
                errorMessage = data.msg;
              } else if (data.error && typeof data.error === 'string') {
                errorMessage = data.error;
              } else if (data.error && typeof data.error === 'object' && data.error.message) {
                errorMessage = data.error.message;
              }
            }
          } else if (error.response.statusText) {
            errorMessage = `${error.response.status} ${error.response.statusText}`;
          }
        } else if (typeof error === 'string') {
          errorMessage = error;
        } else if (typeof error === 'object' && error.toString) {
          errorMessage = error.toString();
        }
      } catch (e) {
        console.error('解析错误信息失败:', e);
        errorMessage = '上传失败，请查看控制台获取详细信息';
      }
      
      // 特殊处理CORS和网络错误
      if (errorMessage.includes('CORS') || errorMessage.includes('Network Error') || errorMessage.includes('ERR_CONNECTION_REFUSED')) {
        errorMessage = '网络连接失败，请检查后端服务是否运行或CORS配置';
      }
      
      // 特殊处理重复上传错误
      if (errorMessage.includes('文件已存在') || errorMessage.includes('不能重复上传')) {
        errorMessage = '文件已存在，不能重复上传。如果已删除，请刷新页面后重试';
      }
      
      fileItem.error = errorMessage;

      this.$message.error(`文件 "${fileItem.name}" 上传失败: ${errorMessage}`);
      this.$emit('upload-error', fileItem, error);
    },

    // 移除文件
    removeFile(fileItem) {
      const index = this.fileList.findIndex(f => f.id === fileItem.id);
      if (index !== -1) {
        this.fileList.splice(index, 1);
      }
    },

    // 生成文件ID
    generateFileId() {
      return 'file_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
    },

    // 格式化文件大小
    formatFileSize(bytes) {
      if (bytes === 0) return '0 B';

      const k = 1024;
      const sizes = ['B', 'KB', 'MB', 'GB'];
      const i = Math.floor(Math.log(bytes) / Math.log(k));

      return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    },

    // 清空上传列表
    clearFileList() {
      this.fileList.forEach(file => {
        if (file.status === 'uploading') {
          this.cancelUpload(file);
        }
      });
      this.fileList = [];
    },

    // 完成并关闭
    handleComplete() {
      // 触发完成事件，让父组件关闭对话框
      this.$emit('upload-all-completed');
    }
  },
  beforeUnmount() {
    // 组件销毁前取消所有上传
    this.fileList.forEach(file => {
      if (file.status === 'uploading') {
        this.cancelUpload(file);
      }
    });
  }
};
</script>

<style scoped>
.big-file-upload {
  max-width: 800px;
  margin: 0 auto;
}

.upload-area {
  border: 2px dashed #ccc;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s ease;
  background-color: #fafafa;
}

.upload-area:hover, .upload-area.drag-over {
  border-color: #409eff;
  background-color: #f0f9ff;
}

.upload-content h3 {
  margin: 10px 0 5px;
  color: #333;
}

.upload-content p {
  color: #666;
  font-size: 14px;
}

.upload-icon {
  font-size: 48px;
  margin-bottom: 10px;
}

.file-list {
  margin-top: 20px;
}

.file-item {
  border: 1px solid #e0e0e0;
  border-radius: 6px;
  padding: 15px;
  margin-bottom: 10px;
  background-color: #fff;
}

.file-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 10px;
}

.file-name {
  font-weight: bold;
  color: #333;
}

.file-size {
  color: #666;
  font-size: 14px;
}

.upload-progress {
  margin: 10px 0;
}

.progress-bar {
  width: 100%;
  height: 6px;
  background-color: #f0f0f0;
  border-radius: 3px;
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  background-color: #409eff;
  transition: width 0.3s ease;
}

.progress-text {
  font-size: 12px;
  color: #666;
  margin-top: 5px;
}

.file-actions {
  display: flex;
  gap: 10px;
  align-items: center;
}

.file-actions button {
  padding: 4px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: white;
  cursor: pointer;
  font-size: 12px;
}

.btn-start { color: #409eff; border-color: #409eff; }
.btn-pause { color: #e6a23c; border-color: #e6a23c; }
.btn-resume { color: #67c23a; border-color: #67c23a; }
.btn-cancel { color: #f56c6c; border-color: #f56c6c; }

.status-completed { color: #67c23a; font-weight: bold; }
.status-error { color: #f56c6c; font-weight: bold; }

.error-message {
  color: #f56c6c;
  font-size: 12px;
  margin-top: 5px;
}

.upload-stats {
  display: flex;
  justify-content: space-around;
  margin-top: 20px;
  padding: 15px;
  background-color: #f5f7fa;
  border-radius: 6px;
}

.upload-actions {
  margin-top: 20px;
  text-align: center;
  padding-top: 20px;
  border-top: 1px solid #e0e0e0;
}

.btn-complete {
  padding: 12px 32px;
  background: #67c23a;
  color: white;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 16px;
  font-weight: bold;
  transition: all 0.3s;
}

.btn-complete:hover {
  background: #5daf34;
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(103, 194, 58, 0.4);
}

.stats-item {
  text-align: center;
}

.stats-item span {
  display: block;
  color: #666;
  font-size: 14px;
}

.stats-item strong {
  display: block;
  color: #333;
  font-size: 18px;
  margin-top: 5px;
}

@media (max-width: 768px) {
  .file-info {
    flex-direction: column;
    align-items: flex-start;
  }

  .upload-stats {
    flex-direction: column;
    gap: 10px;
  }

  .file-actions {
    flex-wrap: wrap;
  }
}
</style>
